package variabilitysmelldetection.measurement;

import java.util.List;

import variabilitysmelldetection.measurement.measures.Measure;
import variabilitysmelldetection.measurement.measures.component.CouplingBetweenObjects;
import variabilitysmelldetection.measurement.measures.component.LinesOfCode;
import variabilitysmelldetection.measurement.measures.component.NumberOfAttributes;
import variabilitysmelldetection.measurement.measures.component.NumberOfConstantRefinements;
import variabilitysmelldetection.measurement.measures.component.NumberOfMethods;
import variabilitysmelldetection.measurement.measures.component.NumberOfOperationOverrides;
import variabilitysmelldetection.measurement.measures.component.WeightedMethodsPerClass;
import variabilitysmelldetection.measurement.measures.method.CyclomaticComplexity;
import variabilitysmelldetection.measurement.measures.method.MethodLinesOfCode;
import variabilitysmelldetection.measurement.measures.method.NumberOfMethodRefinements;
import variabilitysmelldetection.measurement.measures.method.NumberOfParameters;
import variabilitysmelldetection.measurement.measures.spl.NumberOfComponents;
import variabilitysmelldetection.measurement.measures.spl.NumberOfConstants;
import variabilitysmelldetection.measurement.measures.spl.NumberOfFeatures;
import variabilitysmelldetection.measurement.measures.spl.NumberOfOverriddenOperations;
import variabilitysmelldetection.measurement.measures.spl.NumberOfRefinedConstants;
import variabilitysmelldetection.measurement.measures.spl.NumberOfRefinedMethods;
import variabilitysmelldetection.measurement.measures.spl.NumberOfRefinements;
import variabilitysmelldetection.measurement.measures.spl.TotalCouplingBetweenObjects;
import variabilitysmelldetection.measurement.measures.spl.TotalCyclomaticComplexity;
import variabilitysmelldetection.measurement.measures.spl.TotalLinesOfCode;
import variabilitysmelldetection.measurement.measures.spl.TotalNumberOfAttributes;
import variabilitysmelldetection.measurement.measures.spl.TotalNumberOfMethods;
import variabilitysmelldetection.measurement.measures.spl.TotalNumberOfOperationOverrides;
import variabilitysmelldetection.measurement.models.ComponentItem;
import variabilitysmelldetection.measurement.models.Project;


public class Measurement {
	
	private Project project;
	
	private static final Measure[] methodMeasures = {
			new MethodLinesOfCode(),
			new CyclomaticComplexity(),
			new NumberOfParameters(),
			new NumberOfMethodRefinements(),
			new NumberOfOperationOverrides()
	};
	
	private static final  Measure[] componentMeasures = {
			new LinesOfCode(),
			new NumberOfMethods(),
			new NumberOfAttributes(),
			new CouplingBetweenObjects(),
			new WeightedMethodsPerClass(), // execute after CyclomaticComplexity
			new NumberOfConstantRefinements()
	};
	
	private static final  Measure[] projectMeasures = {
			 new TotalLinesOfCode(),
			 new NumberOfComponents(),
			 new TotalNumberOfMethods(),
			 new TotalNumberOfAttributes(),
			 new TotalCyclomaticComplexity(),
			 new TotalCouplingBetweenObjects(),
			 new NumberOfConstants(),
			 new NumberOfRefinements(),
			 new NumberOfRefinedConstants(),
			 new NumberOfMethodRefinements(),
			 new NumberOfRefinedMethods(), // execute after NumberOfMethodRefinements
			 new TotalNumberOfOperationOverrides(),
			 new NumberOfOverriddenOperations(),
			 new NumberOfFeatures()
	};

	public Measurement(Project project) {
		this.project = project;
	}

	public void execute() {
		
		System.out.println("Measuring: "+project.getName()+"...\n");
		
		List<ComponentItem> classes = project.getClassItems();
		
		System.out.println("Measuring methods...");
		for (Measure m : methodMeasures) {
			m.measure(classes);
		}
		
		System.out.println("Measuring classes...");
		for (Measure m : componentMeasures) {
			m.measure(classes);
		}

		System.out.println("Measuring project...");
		for (Measure m : projectMeasures) {
			m.measure(classes);
			project.addMeasure(m);
		}
		
		System.out.println("\ndone.");

	}

	public static Measure[] getMethodMeasures(){
		return methodMeasures;
	}

	public static Measure[] getComponentMeasures() {
		return componentMeasures;
	}

	public Measure[] getProjectMeasures() {
		return projectMeasures;
	}
}